﻿using LitJson;
using LNet;
using OestsCommon.Model;
using OestsDataBase;
using OestsServer.Managers;
using OestsServer.Net;
using System;
using System.Collections.Generic;

namespace OestsServer.Handlers.UnityHandlers
{
    /*
     *  学生请求当前实训的数据 参数:PatternModel
     */
    public class TrainHandler : HandlerBase<UnityClientChannel>
    {
        /// <summary>
        ///
        /// </summary>
        /// <param name="client"></param>
        /// <param name="packet"></param>
        public override PacketKey PKey
        {
            get
            {
                return PacketKey.Train;
            }
        }

        public override void Execute(UnityClientChannel client, Request packet)
        {
            base.Execute(client, packet);
            #region 实训开始

            if (packet.RequestSubCode == SubCode.MultiTrainStart)
            {
                // client.Send(ResponsePacket);
                Execute_StartTrain(client, packet);
            }
            else if (packet.RequestSubCode == SubCode.SceneLoaded)
            {
                Execute_SceneLoaded(client, packet);
            }
            #endregion

            #region 提交实训

            else if (packet.RequestSubCode == SubCode.TrainSubmit)
            {
                TrainData data = JsonMapper.ToObject<TrainData>(packet.DataStr);
                TrainDAL.Add(data);
                ResponsePacket = new Response(packet)
                {
                    ReturnCode = ReturnCode.Success
                };

                client.Send(ResponsePacket);

                //更新错误率
                var errorList = data.GetErrorStat();
                if (errorList != null)
                {
                    foreach (var item in errorList)
                    {
                        TrainDAL.UpdateErrorRateStat(item.projectId, item.taskId, item.stepIndex, item.opIndex, item.errors);
                    }
                }
            }

            else if (packet.RequestSubCode == SubCode.OccTrainSubmit)
            {
                TrainData data = JsonMapper.ToObject<TrainData>(packet.DataStr);
                TrainDAL.AddOccTrain(data);
                ResponsePacket = new Response(packet)
                {
                    ReturnCode = ReturnCode.Success
                };

                client.Send(ResponsePacket);

                //更新错误率

                foreach (var item in data.OperationLog)
                {
                    var record = item.Split('|');

                    var subId = int.Parse(record[0]);

                    var error = record[2] == "0" ? 1 : 0;//0为错误，1为正确

                    TrainDAL.UpdateErrorRateStat(data.ProjectId, data.StudentId, subId, error);

                }
            }

            #endregion

            else if (packet.RequestSubCode == SubCode.GetTrainTaskRanking)
            {
                int taskId = Int32.Parse(packet.DataStr);
                List<TrainData> data = TrainDAL.GetTrainDataByTaskIdOrderByScore(taskId);
                ResponsePacket.DataObject = data;
                client.Send(ResponsePacket);
            }
            else if (packet.RequestSubCode == SubCode.GetStudentTrainData)///与Unity端通信需要增加对应的项目ID
            {
                int stdId = Int32.Parse(packet.DataStr);
                List<TrainData> data = TrainDAL.GetTrainDataByStudentID(stdId);
                ResponsePacket.DataObject = data;
                client.Send(ResponsePacket);
            }
            else if (packet.RequestSubCode == SubCode.UpdateOperation)
            {
                UpdateOperation(client, packet);
            }
            else if (packet.RequestSubCode == SubCode.RecordErrorInfo)
            {
                RecordErrorInfo(client, packet);
            }
            else if (packet.RequestSubCode == SubCode.AbortTrain)
            {
                AbortTrain(client, packet);
            }
            else if (packet.RequestSubCode == SubCode.FinishTrain)
            {
                FinishTrain(client, packet);
            }

            else if (packet.RequestSubCode == SubCode.GetOccSubjects)
            {
                //int taskId = Int32.Parse(packet.DataStr);
                var choices = SubjectDAL.GetOccChoices();
                ResponsePacket = new Response(packet)
                {
                    DataObject = choices
                };
                client.Send(ResponsePacket);
            }

        }
        private void Execute_SceneLoaded(UnityClientChannel client, Request packet)
        {
            DP<int, int> data = JsonMapper.ToObject<DP<int, int>>(packet.DataStr);
            ResponsePacket = new Response(packet)
            {
                ReturnCode = ReturnCode.Success
            };

            if (RoomManager.SceneLoadedInRoom(data.Value1, data.Value2))
            {
                //向所有人发送广播消息
                UnityClientChannel.Signal_Project_Room.Dispatch(client.ProjectType, data.Value1, ResponsePacket);
            }

        }
        private void UpdateOperation(UnityClientChannel client, Request request)
        {
            Struct2<int, object> requestData = JsonMapper.ToObject<Struct2<int, object>>(request.DataStr);
            Response response = new Response(request)
            {
                ReturnCode = ReturnCode.Success
            };
            UnityClientChannel.Signal_Project_Room.Dispatch(client.ProjectType, requestData.Value1, response);
        }

        private void RecordErrorInfo(UnityClientChannel client, Request request)
        {
            Struct2<int, object> requestData = JsonMapper.ToObject<Struct2<int, object>>(request.DataStr);
            Response response = new Response(request)
            {
                ReturnCode = ReturnCode.Success
            };
            UnityClientChannel.Signal_Project_Room.Dispatch(client.ProjectType, requestData.Value1, response);
        }
        private void AbortTrain(UnityClientChannel client, Request request)
        {
            int roomId = int.Parse(request.DataStr);
            AbortTrain(client.ProjectType, roomId, client.User.DBid);
        }

        public static void AbortTrain(ProjectType type, int roomId, int studentId)
        {
            //向房间内成员发送终止任务消息
            Response resDelRoom = new Response(PacketKey.Train, SubCode.AbortTrain)
            {
                ReturnCode = ReturnCode.Success,
                DataObject = new DP<int, int>()
                {
                    Value1 = roomId,
                    Value2 = studentId
                }
            };
            UnityClientChannel.Signal_Project_Room.Dispatch(type, roomId, resDelRoom);


            //删除房间
            RoomManager.DeleteRoom(roomId);

            /********************************** 广播删除后的房间列表信息 *********************************/
            BroadcastRoomList(type, roomId);

        }
        /// <summary>
        /// 房间开始任务
        /// 接收：房间ID int
        /// 房间成员广播 
        /// </summary>
        /// <param name="client"></param>
        /// <param name="packet"></param>
        private void Execute_StartTrain(UnityClientChannel client, Request packet)
        {
            int roomId = int.Parse(packet.DataStr);
            ResponsePacket = new Response(packet)
            {
                ReturnCode = ReturnCode.Success
            };
            //向所有人发送广播消息
            UnityClientChannel.Signal_Project.Dispatch(client.ProjectType, ResponsePacket);
        }

        public static void BroadcastRoomList(ProjectType clientproject, int roomId)
        {
            Response r = new Response(PacketKey.Room, SubCode.RoomList)
            {
                ReturnCode = ReturnCode.Success
            };

            //OCC项目 根据任务ID获取房间列表
            int taskid = RoomManager.GetTaskIdByRoomId(roomId);
            List<Room> roomList = RoomManager.GetRoomList(clientproject, taskid);
            Struct2<int, List<Room>> data = new Struct2<int, List<Room>>() { Value1 = taskid, Value2 = roomList };
            r.DataObject = data;
            //向所有在线成员发送房间列表信息
            UnityClientChannel.Signal_Project.Dispatch(clientproject, r);
        }


        private void FinishTrain(UnityClientChannel client, Request request)
        {
            int roomId = int.Parse(request.DataStr);
            if (RoomManager.CheckIsTrainFinishInRoom(roomId, client.User.DBid))//判断房间内所有成员都完成实训
            {
                //向房间内成员发送实训完成消息 房间id
                ResponsePacket = new Response(request);
                UnityClientChannel.Signal_Project_Room.Dispatch(client.ProjectType, roomId, ResponsePacket);

                //删除房间
                RoomManager.DeleteRoom(roomId);

                /********************************** 广播删除后的房间列表信息 *********************************/
                BroadcastRoomList(client.ProjectType, roomId);
            }

        }
    }
}
